<?php
/**
 * @author Kumar Swami Reddy
 * @email  kumar08DOTreddyATgmailDOTcom
 *
 */
class Orm{
	private $table_name;
	private $table_prefix;
	private $class_name;
	private $foreign_table_names = array();
	private $foreign_field_names = array();
	private $related = 0;
	private $foreign_obj;
	
	/**
	 * @param $table_name
	 * 
	 */
	function __construct($table_name){
		global $mosConfig_dbprefix;
		$table_prefix = $mosConfig_dbprefix.Config::resman_prefix;
		$this->table_name = $table_prefix.$table_name;
		$this->table_prefix = $table_prefix;
	}
	
	/**
	 * @param $arg
	 * @return object if the arguement is an integer
	 * else will return an array of objects
	 */
	function find($arg){
		$type = gettype($arg);
		switch($type){
			case "integer":
				$result = mysql_query("SELECT * FROM `$this->table_name` WHERE `id` = '".$arg."'");
				$return = $this->set_column_names_as_instance_var($result, $type);
				break;
			case "array":
				$condition_str = "";
				foreach ($arg as $key => $value){
					$condition_str .= "`$key` = '$value' AND ";
				}
				$condition_str = substr_replace($condition_str ,"",-5);
				$result = mysql_query("SELECT * FROM `$this->table_name` WHERE $condition_str ORDER BY `id` DESC");
				$return = $this->set_column_names_as_instance_var($result, $type);
				break;
			case "string":
				if(strtolower($arg) == "all"){
					$result = mysql_query("SELECT * FROM `$this->table_name` ORDER BY `id` DESC");
					$return = $this->set_column_names_as_instance_var($result, $type);
				}
				break;
		}
		return $return;
	}

	/**
	 * @return unknown_type
	 */
	function find_unique(){
		
	}
	
	function first(){
		$result = mysql_query("SELECT * FROM `$this->table_name` ORDER BY `id` ASC LIMIT 1");
		$this->set_column_names_as_instance_var($result, "");
	}

	function last(){
		$result = mysql_query("SELECT * FROM `$this->table_name` ORDER BY `id` DESC LIMIT 1");
		$this->set_column_names_as_instance_var($result, "");
	}

	/*
	 * this function will be used in the future to support
	 * convention over configuration pattern as supported in Rails
	 */
	private function set_table_name(){
		$this->class_name = get_class($this);
	}
	
	/*
	 * the array_push_assoc can create a problem if one of the column name of the
	 * table matches with the linked table name, as it will override the value.
	 * 
	 * will have to fix this issue
	 */
	private function set_column_names_as_instance_var($result, $type){
		if($type == "integer"){
			$return = @mysql_fetch_assoc($result);
			// some code can be reduced at this point
			if($this->related == 1){
				foreach ($this->foreign_table_names as $key => $value){
					$related_table = $this->build_relation($return,$key);
					array_push_assoc($return, $related_table);
				}
			}
			$return = (object)$return;
		}
		else{
			$return = array();
			while ($row = @mysql_fetch_assoc($result)) {
				if($this->related == 1){
					foreach ($this->foreign_table_names as $key => $value){
						$related_table = $this->build_relation($row,$key);
						array_push_assoc($row, $related_table);
					}
				}
				array_push($return,(object)$row);
			}
		}
		@mysql_free_result($result);
		return $return;
	}
	
	/**
	 * @param $sql
	 * @param $flag
	 * set $flag to 1 if you want an array as a object (if the output will be a single row) 
	 * or set to "" if you want an array of objects (if the output will be multiple row)
	 */
	public function select_row_query($sql, $flag){
		$result = mysql_query($sql) or die($sql);
		$return = $this->set_column_names_as_instance_var($result, gettype($flag));
		return $return;
	}
	
	/**
	 * The functions "insert_row_query()" and "delete_row_query()" will be merged
	 * 
	 */
	public function insert_row_query($sql){
		if(mysql_query($sql)){
			return array("msg"=>"", "error"=>0);
		}
		else{
			return array("msg"=>mysql_error(), "error"=>1);
		}
	}
	
	public function delete_row_query($sql){
		if(mysql_query($sql)){
			return array("msg"=>$sql, "error"=>0);
		}
		else{
			return array("msg"=>mysql_error(), "error"=>1);
		}
	}
	
	public function count($sql){
		if(strtolower($sql) == "all") $query = "SELECT * FROM `$this->table_name`";
		else $query = $sql;
		
		$result = mysql_query($query) or die(mysql_error());
		return mysql_num_rows($result);
	}
	
	public function get_table_name(){
		return $this->table_name;
	}
	
	public function related_to_table_by_field_name($table_name, $field_name){
		array_push($this->foreign_table_names, $table_name);
		array_push($this->foreign_field_names, $field_name);
		$this->related = 1;
	}
	
	private function build_relation($obj, $key){
		$table_name = $this->table_prefix.$this->foreign_table_names[$key];
		$result = mysql_query("SELECT * FROM `".$table_name."` WHERE `id` = ".$obj[$this->foreign_field_names[$key]]);
		return array($this->foreign_table_names[$key] => (object)@mysql_fetch_assoc($result));
	}
	
	public function insert_or_update($fields, $identifiers){
		if(!empty($identifiers)) $sql = "UPDATE `".$this->table_name."` SET ";
		else $sql = "INSERT INTO `".$this->table_name."` SET ";
		foreach($fields as $key=>$value){
			$sql .= "`".$key."` = '".$value."', ";
		}
		$sql = substr($sql, 0, -2);
		if(!empty($identifiers)){
			$sql .= " WHERE ";
			foreach($identifiers as $key=>$value){
				$sql .= "`".$key."` = '".$value."' AND ";
			}
			$sql = substr($sql, 0, -5);
		}
//		return $sql;
		if(mysql_query($sql)){
			return array("error_msg"=>"", "error"=>0);
		}
		else{
			return array("error_msg"=>mysql_error(), "error"=>1);
		}
	}
	
	public function debug($obj){
		if(is_array($obj)) print_r($obj);
		else echo $obj;
	}
	
	public function to_string(){
		return "Class: ".get_class($this);
	}
}
?>